package com.vsu.bookstore.mvc.ui.widgets;

import java.math.BigDecimal;
import java.util.Iterator;

import org.vaadin.hene.expandingtextarea.ExpandingTextArea;
import org.vaadin.henrik.superimmediatetextfield.SuperImmediateTextField;
import org.vaadin.henrik.superimmediatetextfield.SuperImmediateTextField.KeyPressEvent;
import org.vaadin.henrik.superimmediatetextfield.SuperImmediateTextField.KeyPressListener;
import org.vaadin.imagefilter.Image;
import org.vaadin.teemu.ratingstars.RatingStars;

import com.jensjansson.pagedtable.PagedTable;
import com.vaadin.addon.sqlcontainer.SQLContainer;
import com.vaadin.addon.sqlcontainer.query.Filter;
import com.vaadin.addon.sqlcontainer.query.Filter.ComparisonType;
import com.vaadin.data.Item;
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
import com.vaadin.incubator.cufonlabel.CufonLabel;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Select;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Window.Notification;
import com.vsu.bookstore.BookstoreApplication;
import com.vsu.bookstore.mvc.model.bean.BookStoreItem;
import com.vsu.bookstore.util.DataUtils;
import com.vsu.bookstore.util.DatabaseHelper;
import com.vsu.bookstore.util.UserSession;

@SuppressWarnings("serial")
public class BookStoreTable extends PagedTable
{
  public static final int DEFAULT_PAGE_LENGTH = 4;

  public static final int SINGLE_MODE_PAGE_LENGTH = 10;

  private static final int DESCRIPTION_LIMIT = 500;

  private int tablePageLength = DEFAULT_PAGE_LENGTH;

  private final HorizontalLayout headerContents = new HorizontalLayout();

  private Object categoryId = null;

  private String categoryTitle = "";

  private final ColumnGenerator imageColumnGenerator = new ColumnGenerator()
  {
    public Component generateCell(final Table source, final Object itemId, final Object columnId)
    {
      final VerticalLayout layout = new VerticalLayout();
      layout.setMargin(false);
      layout.setSpacing(false);
      layout.setWidth("100%");
      layout.addListener(new LayoutClickListener()
      {
        public void layoutClick(final LayoutClickEvent event)
        {
          final BookStoreItem bean = DataUtils.getBeanById(itemId);
          getApp().ui().showDetailed(bean);
        }
      });
      final Item item = DatabaseHelper.get().getItemContainer().getItem(itemId);
      if (item == null)
        return null;
      final byte[] value =
        (byte[]) item.getItemProperty("Image").getValue();
      final Image image = new Image();
      image.load(value);
      layout.addComponent(image);
      layout.setComponentAlignment(image, Alignment.TOP_CENTER);
      return layout;
    }
  };

  private final ColumnGenerator titleColumnGenerator = new ColumnGenerator()
  {
    public Component generateCell(final Table source, final Object itemId, final Object columnId)
    {
      final VerticalLayout layout = new VerticalLayout();
      layout.setWidth("100%");
      layout.setMargin(true);
      layout.setSpacing(false);
      layout.addStyleName("hugefont");

      final Item item = DatabaseHelper.get().getItemContainer().getItem(itemId);

      String description = (String)item.getItemProperty("Description").getValue();
      if (description != null &&
          description.length() > DESCRIPTION_LIMIT)
        description = description.substring(0, DESCRIPTION_LIMIT - 4) + "...";
      final ExpandingTextArea descField = new ExpandingTextArea();
      descField.setWidth("100%");
      descField.setValue(description);
      descField.setReadOnly(true);

      final RatingStars stars = new RatingStars();
      stars.setMaxValue(5);
      stars.setImmediate(true);
      stars.setValue(DataUtils.getBookStoreItemRating(item));
      stars.addListener(new ValueChangeListener()
      {
        public void valueChange(final com.vaadin.data.Property.ValueChangeEvent event)
        {
          final UserSession session = getApp().getSession();
          if (!session.votedFor((Integer)item.getItemProperty("ID").getValue()))
            getWindow().showNotification("Your vote accepted!", Notification.TYPE_WARNING_MESSAGE);
          stars.setValue(session.makeVote(item, (Double)event.getProperty().getValue()));
        }
      });


      final CartButtons cartButtons = new CartButtons();
      cartButtons.addAddListener(new Button.ClickListener()
      {
        public void buttonClick(final ClickEvent event)
        {
          final BookStoreItem bean = getApp().getSession().addToCart(item);
          getApp().ui().addToCartPanel(bean, true);
        }
      });
      cartButtons.addRemoveListener(new Button.ClickListener()
      {
        public void buttonClick(final ClickEvent event)
        {
          final BookStoreItem bean = getApp().getSession().removeFromCart(item);
          getApp().ui().addToCartPanel(bean, false);
        }
      });
      final Label priceLabel = new EuroToRubleLabel();
      priceLabel.setValue(((BigDecimal)item.getItemProperty("Price").getValue()).doubleValue());
      final HorizontalLayout bottomLayout = new HorizontalLayout();
      bottomLayout.setWidth("100%");
      bottomLayout.addStyleName("semihugefont");
      bottomLayout.addComponent(stars);
      bottomLayout.addComponent(priceLabel);
      bottomLayout.addComponent(cartButtons);



      bottomLayout.setComponentAlignment(stars, Alignment.TOP_LEFT);
      bottomLayout.setComponentAlignment(priceLabel, Alignment.BOTTOM_RIGHT);
      bottomLayout.setComponentAlignment(cartButtons, Alignment.BOTTOM_RIGHT);


      bottomLayout.setExpandRatio(priceLabel, 0.15f);
      bottomLayout.setExpandRatio(stars, 1f);

      final Label titleLabel = new CufonLabel((String)item.getItemProperty("Title").getValue(), "GoodDog");
      layout.addComponent(titleLabel);
      layout.addComponent(descField);
      layout.addComponent(bottomLayout);
      layout.setComponentAlignment(titleLabel, Alignment.TOP_LEFT);
      layout.setComponentAlignment(descField, Alignment.TOP_LEFT);
      return layout;
    }
  };

  public BookStoreTable(final Object id, final String title)
  {
    super();
    categoryId = id;
    categoryTitle = title;
    setSizeFull();
    setEditable(true);
    setSelectable(false);
    setImmediate(true);
    final SQLContainer container =
      DatabaseHelper.get().getContainerByCategoryId(id);
    setContainerDataSource(container);
    addGeneratedColumn("Picture", imageColumnGenerator);
    addGeneratedColumn("Contents", titleColumnGenerator);
    setVisibleColumns(new Object[]{"Picture", "Contents"});
    setColumnHeaders(new String[]{"Preview","Title and description"});
    setColumnExpandRatio("Picture", 0.15f);
    setColumnExpandRatio("Contents", 0.7f);
    prepareTableHeader();
    setPageLength(DEFAULT_PAGE_LENGTH);
  }

  @Override
  public HorizontalLayout createControls()
  {
    final HorizontalLayout layout = super.createControls();
    final Iterator<Component> it = layout.getComponentIterator();
    while (it.hasNext())
    {
      final Component component = it.next();
      if (component instanceof HorizontalLayout)
      {
        final Iterator<Component> childIt = ((HorizontalLayout)component).getComponentIterator();
        while (it.hasNext())
        {
          final Component childComponent = childIt.next();
          if (childComponent instanceof Select)
          {
            ((HorizontalLayout)component).removeAllComponents();
            break;
          }
        }
      }
    }
    setPageLength(DEFAULT_PAGE_LENGTH);
    layout.setSizeUndefined();
    return layout;
  }

  private BookstoreApplication getApp()
  {
    return (BookstoreApplication)getApplication();
  }


  public HorizontalLayout getHeaderContents()
  {
    return headerContents;
  }

  @Override
  public int getPageLength()
  {
    return tablePageLength;
  }

  public int getTablePageLength()
  {
    return tablePageLength;
  }
  private void prepareTableHeader()
  {
    headerContents.setWidth("100%");
    headerContents.setMargin(true);
    headerContents.setSpacing(true);
    final HorizontalLayout titleLayout = new HorizontalLayout();
    titleLayout.addStyleName("hugefont");
    titleLayout.addComponent(new Label(categoryTitle));
    titleLayout.addListener(new LayoutClickListener()
    {
      public void layoutClick(final LayoutClickEvent event)
      {
        if (event.isDoubleClick())
          getApp().ui().onCategoryHeaderDblClicked(categoryId);
      }
    });
    final SuperImmediateTextField filterField = new SuperImmediateTextField();
    filterField.setSizeUndefined();
    filterField.addListener(new KeyPressListener()
    {
      public void keyPressed(final KeyPressEvent event)
      {
        final SQLContainer container = ((SQLContainer)getContainerDataSource());
        final String val = filterField.getValue().toString();
        container.removeAllContainerFilters();
        container.addContainerFilter("Title",val, true, false);
        container.addFilter(new Filter("Group_ID", ComparisonType.EQUALS, categoryId));
        sort(new Object[]{"Title"}, new boolean[]{true});
      }
    });
    final HorizontalLayout headers = createControls();
    headerContents.addComponent(titleLayout);
    headerContents.addComponent(headers);
    headerContents.addComponent(filterField);
    headerContents.setExpandRatio(titleLayout, 1.0f);
    headerContents.setComponentAlignment(filterField, Alignment.MIDDLE_RIGHT);
    headerContents.setComponentAlignment(headers, Alignment.MIDDLE_RIGHT);
    headerContents.setComponentAlignment(titleLayout, Alignment.MIDDLE_LEFT);
  }

  public void setTablePageLength(final int tablePageLength)
  {
    setPageLength(tablePageLength);
    this.tablePageLength = tablePageLength;
    sort(new Object[]{"Title"}, new boolean[]{true});
  }
}
